package br.usp.ime.origami.foldcut.io;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

import org.apache.batik.svggen.SVGGraphics2DIOException;

import br.usp.ime.origami.foldcut.gui.util.Figure;
import br.usp.ime.origami.foldcut.gui.util.OrigamiShape;
import br.usp.ime.origami.view.Drawable;

public class Simulator
{
	private List<Figure> backGround;

	private List<List<Figure>> steps;

	private Map<Integer, List<Figure>> backGrounds;

	private static Simulator simulator;

	private int current;

	private Simulator()
	{
		steps = new ArrayList<List<Figure>>();
		backGround = new ArrayList<Figure>();
		backGrounds = new HashMap<Integer, List<Figure>>();
		current = -1;
	}

	public static Simulator getInstance()
	{
		if (simulator == null)
		{
			simulator = new Simulator();
		}
		return simulator;
	}

	public void addSimulationStep(List<Drawable> drawables)
	{
		List<Figure> figures = new ArrayList<Figure>();
		for (Drawable drawable : drawables)
		{
			figures.add(drawable.toFigure());
		}

		int i = this.steps.size();
		this.steps.add(i, figures);
		backGrounds.put(i, backGround);
	}

	public void addSimulationStep(Drawable... list)
	{
		addSimulationStep(Arrays.asList(list));
	}

	public void setBackground(List<? extends Drawable> drawables)
	{
		backGround = new ArrayList<Figure>();

		for (Drawable drawable : drawables)
		{
			backGround.add(drawable.toFigure());
		}

	}

	public void setBackground(Drawable... list)
	{
		setBackground(Arrays.asList(list));
	}

	public void setBackground(Drawable drawable)
	{
		backGround = new ArrayList<Figure>();
		backGround.add(drawable.toFigure());
	}

	private void draw(Graphics2D g, List<OrigamiShape> shapes, float delta)
	{

		for (OrigamiShape myShape : shapes)
		{
			g.setColor(OrigamiShape.DrawScheme.getColor(myShape.getScheme()));
			g.setStroke(OrigamiShape.DrawScheme.getStroke(myShape.getScheme(),delta));
			g.draw(myShape.getShape());
		}
	}

	public void next(int steps)
	{
		if (current + steps < this.steps.size())
		{
			current += steps;
		}
	}

	public void previous(int steps)
	{
		if (current - steps >= 0)
		{
			current = current - steps;
		}
	}

	public BufferedImage getBufferedImageActual()
	{
		BufferedImage buffer = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB_PRE);
		Graphics2D graphics2D = buffer.createGraphics();

		drawActualShapes(graphics2D);

		return buffer;
	}

	private void drawActualShapes(Graphics2D graphics2D)
	{
		graphics2D.translate(20, 20);
		graphics2D.setStroke(new BasicStroke(2.0f));

		for (Figure figure : backGrounds.get(current))
		{
			List<OrigamiShape> shapes = figure.getShapes();
			draw(graphics2D, shapes, -.5f);
		}

		graphics2D.setStroke(new BasicStroke(3.5f));
		for (Figure figure : steps.get(current))
		{
			List<OrigamiShape> shapes = figure.getShapes();
			draw(graphics2D, shapes, 0);
		}

	}

	private void takeSnapshot() throws UnsupportedEncodingException, SVGGraphics2DIOException, FileNotFoundException
	{

		new SVGSnapshot().takeSnapshot(""+current, backGrounds.get(current), steps.get(current));

	}

	private void show(JFrame frm)
	{
		frm.getContentPane().removeAll();

		if (getBufferedImageActual() != null)
		{
			ImageIcon img = new ImageIcon(getBufferedImageActual());
			JLabel label = new JLabel(img);
			frm.getContentPane().add(label);
		}

		frm.pack();
		frm.setVisible(true);
	}

	public void clearBackGround()
	{
		backGround = new ArrayList<Figure>();

	}

	public int getStep()
	{
		return current;
	}

	public int getStepCount()
	{
		return steps.size();
	}

}
